const _ = require('lodash');
const moment = require('moment');
const auto = require('async/auto');
const Table = require('./HtmlTable');
const ECharts = require('./ECharts');

const tableWidth = '';
const borderStyle = 'border: 1px solid #000';
const alignCenter = 'text-align: center';

let app, model, between, lte, gte, or, $in;

class ReportData {
    constructor(_app) {
        app = _app;
        model = _app.model;
        const Op = _app.Sequelize.Op;
        lte = Op.lte;
        gte = Op.gte;
        or = Op.or;
        between = Op.between;
        $in = Op.in;
    }

    /**
     * 日志的数据
     * @param project_id
     * @param report_id
     * @param index
     * @param date
     * @returns {Promise<any>}
     */

    async get({project_id, report_id, date, index}) {
        const {
            DetailAnchor, Platform, DetailAnchorData, File, DetailAnchorSchedule,
            DailyCategory, DailyCategoryData, DailyPlatformCategory,
            Project, Report,
        } = model;

        let report;
        if (!_.isEmpty(index)) {
            report = await Report.findOne({where: {index}});
        } else if (report_id > 0) {
            report = await Report.findByPk(report_id);
        }
        else if (!_.isEmpty(date) || !_.isEmpty(project_id)) {
            report = await Report.findOne({where: {project_id, created_at: date}});
        }

        if (!report)
            throw new Error('无法找到日志');

        report = report.toJSON();

        const now = new Date(report.created_at);

        const yesterday = moment(now).subtract(1, 'day').format('YYYY-MM-DD');
        const start = moment(now).startOf('day').toDate(), end = moment(now).endOf('day').toDate();
        let project = await Project.findByPk(report.project_id);
        project = project.toJSON();
        return new Promise(resolve => {
            auto({
                    //直播记录
                    async schedules() {
                        let schedulesRes = await DetailAnchorSchedule.findAll({
                            where: {
                                project_id: project.id, [or]: {
                                    start: {[between]: [start, end]},
                                    end: {[between]: [start, end]}
                                }
                            },
                            order: [['end', 'asc']],
                            include: [
                                {model: Platform, as: 'platform'},
                                {
                                    model: DetailAnchor,
                                    as: 'anchor',
                                    include: [{
                                        model: DetailAnchorData,
                                        as: 'data',
                                        limit: 1,
                                        order: [['created_at', 'desc']]
                                    }]
                                },
                                {
                                    model: File,
                                    as: 'images',
                                    required: false,
                                    where: {selected: true},
                                },
                                {model: File, as: 'image', required: false,}
                            ],
                        });
                        schedulesRes = _.sortBy(schedulesRes, 'end');
                        const schedules = {};
                        schedulesRes.forEach(schedule => {
                            if (!schedules[schedule.id])
                                schedules[schedule.id] = schedules[schedule.id]
                        });
                        return schedulesRes.map(s => {
                            const j = s.toJSON();
                            j.qrcode = j.qrcode ? 1 : '';
                            j.start = moment(j.start).format('MM月DD日 HH点mm分');
                            j.end = moment(j.end).format('MM月DD日 HH点mm分');
                            return j;
                        });
                        // return Object.values(schedules);
                    },
                    //当天的直播类型数据
                    async categoriesData() {
                        let pcId = [];
                        project.options.aggregation.forEach(item => {
                            pcId = pcId.concat(item.data);
                        });
                        pcId = _.compact(_.uniq(pcId));
                        // console.log('categoriesData 1', pcId);

                        const data = await DailyPlatformCategory.findAll({
                            where: {id: {[$in]: pcId}},
                            include: [{model: Platform}, {model: DailyCategory}]
                        });
                        // console.log('categoriesData 2', data.length);
                        return _.keyBy(data, 'id');
                    },
                    current: ['categoriesData', async res => {
                        const dpc = res.categoriesData;
                        return await DailyCategoryData.findAll({
                            where: {
                                daily_platform_category_id: {[$in]: Object.keys(dpc)},
                                created_at: report.created_at
                            }
                        });
                    }],
                    yesterday: ['categoriesData', async res => {
                        const dpc = res.categoriesData;
                        // console.log('yesterday', Object.keys(dpc));
                        return await DailyCategoryData.findAll({
                            raw: true,
                            where: {
                                daily_platform_category_id: {[$in]: Object.keys(dpc)},
                                created_at: yesterday,
                            },
                            attributes: ['active', 'daily_platform_category_id'],
                        });
                    }],
                    categories: ['categoriesData', 'current', 'yesterday', async res => {
                        let {current, yesterday, categoriesData} = res;
                        //计算趋势
                        _.each(current, (today, index) => {
                            current[index] = today = today.toJSON();
                            let yesterdayData = _.find(yesterday, {daily_platform_category_id: today.daily_platform_category_id});
                            // console.log('趋势', today, yesterdayData);
                            if (yesterdayData) {
                                if (today.active > yesterdayData.active)
                                    today.trend = '↑';
                                else if (today.active < yesterdayData.active)
                                    today.trend = '↓';
                                else
                                    today.trend = '=';
                            } else {
                                today.trend = '';
                            }
                        });
                        const dateGroup = _.keyBy(current, 'daily_platform_category_id');

                        //整理分类
                        _.each(project.options.aggregation, item => {
                            item.data.forEach(id => {
                                let data = {
                                    category: categoriesData[id].daily_category.name,
                                    platform: categoriesData[id].platform.name,
                                    _new: 0,
                                    watch: 0,
                                    open: 0,
                                    active: 0,
                                    gift: 0,
                                    rank: '',
                                    trend: '',
                                };

                                if (dateGroup[id]) {
                                    data.trend = dateGroup[id].trend;
                                    data.rank = dateGroup[id].rank;
                                    data._new = dateGroup[id]._new;
                                    data.watch = dateGroup[id].watch;
                                    data.open = dateGroup[id].open;
                                    data.active = dateGroup[id].active;
                                    data.gift = Number(dateGroup[id].gift);
                                }
                                dateGroup[id] = data;
                            });
                        });
                        const data = {};
                        //统计分类
                        _.each(project.options.aggregation, item => {
                            let _data = {};
                            item.data.forEach(id => {
                                let platform = dateGroup[id].platform;
                                if (_data[platform]) {
                                    _data[platform].category.push(dateGroup[id].category);
                                    _data[platform]._new += dateGroup[id]._new;
                                    _data[platform].watch += dateGroup[id].watch;
                                    _data[platform].open += dateGroup[id].open;
                                    _data[platform].active += dateGroup[id].active;
                                    _data[platform].gift += Number(dateGroup[id].gift);
                                    _data[platform].rank += '/' + dateGroup[id].rank;
                                    _data[platform].trend += '/' + dateGroup[id].trend;
                                } else {
                                    _data[platform] = Object.assign({}, dateGroup[id]);
                                    _data[platform].category = [dateGroup[id].category];
                                }
                            });
                            data[item.name] = Object.values(_data);
                        });
                        return data;
                    }],
                },
                (err, res) => {
                    if (err)
                        console.log('report', err);
                    res.report = report;
                    res.project = project;
                    if (!res.schedules)
                        res.schedules = [];
                    if (!res.categories)
                        res.categories = {};
                    resolve({schedules: res.schedules, categories: res.categories, project, report});
                }
            );
        });
    }


    /**
     * 获取日志的活跃主播趋势
     * @param project_id
     * @param start
     * @param end
     * @returns {Promise<{data: *}>}
     */
    async getActiveAnchor({id: project_id, start, end}) {
        const {DailyCategory, DailyCategoryData, Platform, Project, DailyPlatformCategory} = model;
        const project = await Project.findByPk(project_id);
        let pcId = [];
        project.options.aggregation.forEach(item => {
            pcId = pcId.concat(item.data);
        });
        pcId = _.compact(_.uniq(pcId));
        // console.log({pcId});
        let [originalData, platformCategory] = await Promise.all([
            DailyCategoryData.findAll({
                where: {
                    daily_platform_category_id: {[$in]: pcId},
                    created_at: {[gte]: start, [lte]: end}
                },
                attributes: [
                    'created_at', 'daily_platform_category_id', 'platform_id', 'daily_category_id', 'active'],
            }),
            DailyPlatformCategory.findAll({
                where: {id: {[$in]: pcId}},
                include: [{model: Platform}, {model: DailyCategory}]
            })]);
        // console.log('data length', originalData.length);
        platformCategory = _.keyBy(platformCategory, 'id');
        const dateGroup = _.groupBy(originalData, 'daily_platform_category_id');
        end = moment(end);
        let aggregationData = {}, platformCategoryData = {}, date = [];

        pcId.forEach(id => {
            let _start = moment(start);
            if (!platformCategoryData[id])
                platformCategoryData[id] = {};
            let data = dateGroup[id];
            while (_start <= end) {
                const date = _start.format('YYYY-MM-DD');
                let active = 0;
                if (!_.isEmpty(data)) {
                    let find = _.find(data, {created_at: date});
                    if (find) active = find.active;
                }
                platformCategoryData[id][date] = active;
                _start.add(1, 'day');
            }
        });

        let _start = moment(start);
        while (_start <= end) {
            date.push(_start.format('MM月DD日'));
            _start.add(1, 'day');
        }

        _.each(project.options.aggregation, item => {
            let data = aggregationData[item.name] = {};
            item.data.forEach(id => {
                let {platform_id} = platformCategory[id];
                if (data[platform_id])
                    data[platform_id].data = Object.values(platformCategoryData[id]).map((active, i) =>
                        data[platform_id].data[i] += active
                    );
                else
                    data[platform_id] = {
                        data: Object.values(platformCategoryData[id]),
                        name: platformCategory[id].platform.name,
                        type: 'line',
                    };
            });
        });
        _.each(aggregationData, (data, key) => {
            aggregationData[key] = Object.values(data);
        });
        return {date, data: aggregationData};
    }

    /**
     * 将日志数据渲染成HTML，用于发送邮件
     * @param report_id
     * @param appendContent
     * @param {Boolean} isCreateECharts 是否创建ECharts图片文件
     * @returns {Promise<{subject: string, html: string}>}
     */
    async renderHtml(report_id, appendContent, isCreateECharts = true) {
        const {project, report, schedules, categories} = await this.get({report_id});

        let allPlatform = '';
        {
            const header = ['排名', '平台', '*活跃主播', '新增主播', '开播数', '礼物价值', '总人气', '昨日对比'];
            _.each(categories, (category, name) => {
                const table = new Table(report.created_at + ' ' + name + ' 数据');
                table.header(header, project.options.color);
                table.sumStartAt(2);
                table.sumSkip(7);
                table._rows = category.map(data =>
                    [data.rank, data.platform, data.active, data._new, data.open, data.gift, data.watch, data.trend]
                );
                allPlatform += table + '<br>';
            });
        }

        /**活跃主播趋势 区块*/
        let activeAnchorTable = '';
        {
            const start = moment(report.created_at).subtract(6, 'days');
            let {date, data} = await this.getActiveAnchor({
                id: project.id, start: start.format('YYYY-MM-DD'), end: report.created_at
            });
            let header = ['平台'].concat(date);
            let index = 0;
            _.each(data, (data, category) => {
                //表格部分
                let table = new Table(category + ' 各平台活跃主播统计数据');
                table.header(header, project.options.color);
                table._rows = Object.values(data).map(item => {
                    return [item.name].concat(item.data);
                });
                activeAnchorTable += table.toString() + '<br/>';


                //图表部分
                data.forEach(data => {
                    data.label = {normal: {show: true}};
                });

                let option = {
                    backgroundColor: '#fff',
                    title: {text: `${category} 各平台活跃主播变化趋势`},
                    grid: {
                        left: '3%',
                        right: '4%',
                        bottom: '3%',
                        containLabel: true
                    },
                    legend: {data: _.map(data, 'name'), right: '0%', top: '5%'},
                    xAxis: {data: date},
                    yAxis: {},
                    series: data,
                };

                let file = report_id + '_' + index;

                //创建ECharts的图表图片文件
                if (isCreateECharts) {
                    ECharts({
                        option,
                        path: app.config.screenshot.path,
                        file
                    });

                    //插入邮件图表到数据库，并设为已使用
                    app.model.File.upsert({file, selected: true,}).then(() => {
                        return app.model.File.findOne({where: {file}});
                    }).then(file => {
                        app.model.ReportImage.upsert({file_id: file.id, report_id: report.id});
                    });
                }

                activeAnchorTable += `<img src="https://live.beijingzhuyou.com/pic/${file}" />`;
                index++;
            });
        }


        /**主播数据*/
        const scheduleTable = new Table(report.created_at + ' 直播反馈信息');
        {
            const platformData = _.groupBy(schedules, 'platform_id');
            scheduleTable.header(['平台', '主播', '开始时间', '结束时间', '最高在线', '二维码', '硬广'], project.options.color);
            let hide = project.options.hide;
            if (!hide.danmu)
                scheduleTable._header.push('弹幕数量');
            if (!hide.cost)
                scheduleTable._header.push('成本');
            if (!hide.click)
                scheduleTable._header.push('点击');
            if (!hide.added)
                scheduleTable._header.push('新增');
            if (!hide.reflux)
                scheduleTable._header.push('回流');
            scheduleTable.sumStartAt(4);
            scheduleTable.sumSkip([]);
            _.each(platformData, schedules => {
                let platform = schedules[0].platform.name;
                schedules.forEach((schedule, i) => {
                    let qrcode = schedule.qrcode ? 1 : '';
                    let yingguang = schedule.image ? 1 : '';
                    let row = [platform, schedule.anchor.name, schedule.start, schedule.end, schedule.online, qrcode, yingguang];
                    if (!hide.danmu)
                        row.push(schedule.anchor.data[0] ? schedule.anchor.data[0].danmu : 0);
                    if (!hide.cost)
                        row.push(schedule.anchor.data[0] ? schedule.anchor.data[0].cost : 0);
                    if (!hide.click)
                        row.push(schedule.anchor.data[0] ? schedule.anchor.data[0].click : 0);
                    if (!hide.added)
                        row.push(schedule.anchor.data[0] ? schedule.anchor.data[0].added : 0);
                    if (!hide.reflux)
                        row.push(schedule.anchor.data[0] ? schedule.anchor.data[0].reflux : 0);
                    scheduleTable.row(row);
                });
            });
        }

        /**硬广情况*/
        let yingGuang = '无';
        {
            let list = schedules.filter(schedule => schedule.image_id > 0);
            if (list.length > 0)
                yingGuang = '';
            list.forEach(schedule => {
                yingGuang += `<table style="margin:0 10px 10px 0;display:inline-block;border-collapse: collapse;${borderStyle};${tableWidth};${alignCenter};">
<tr style="background:${project.options.color};${borderStyle};color:#fff;">
<td>${schedule.platform.name} - ${schedule.anchor.name}</td>
</tr>
<tr>
<td>
<a href="https://live.beijingzhuyou.com/pic/${schedule.image.file}" target="_blank">
<img src="https://live.beijingzhuyou.com/pic/${schedule.image.file}_small">
</a>
</td>
</tr>
</table>`;
            });
        }
        const html = `<div style="padding: 10px 20px;font-size:16px;">
<div style="color: #999;font-size:12px">打开 <a href="https://live.beijingzhuyou.com/vpr/${report.index}" target="_blank">网址</a> 有更好的观看数据体验</div>
<h2 style="${alignCenter};">${project.name + ' ' + report.created_at} 数据日报</h2>
<h4>一，总体数据情况</h4>
${allPlatform}
${activeAnchorTable}
<br>
<h4>二，主播开播情况</h4>
${scheduleTable}
<h4>三，硬广情况</h4>
${yingGuang}
<h4>附加信息</h4>
<pre style="font-size:16px;">${appendContent}</pre>
</div>`;
        let now = moment(report.created_at).format('YYYY年MM月DD日');
        return {
            subject: `${project.name} ${now} 日志报告`,
            html,
            text: `请打开 https://live.beijingzhuyou.com/vpr/${report.index} 浏览`
        };
    }
}


module.exports = ReportData;